package com.movies.controller;

import com.movies.model.MovieUser;
import com.movies.repository.UserMapper;
import com.movies.utils.RC2Utils;
import com.movies.vo.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;


@RestController
@RequestMapping("/rest")
public class AuthController {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @RequestMapping("/login")
    public Response login(@RequestBody MovieUser movieUser, HttpServletRequest request) throws IOException {
        try {
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(movieUser.getUsername(), RC2Utils.encrypt(movieUser.getPassword()));
            Authentication authentication = authenticationManager.authenticate(authRequest);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            /**
             * 该操作在SecurityContextHolder.getContext().setAuthentication(authentication)时已经完成
             */
            /*HttpSession session = request.getSession();
            session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());*/
        } catch (UsernameNotFoundException e) {
            Response response = new Response(false);
            response.getHeader().setResultMessage("用户不存在");
            return response;
        } catch (AuthenticationException e) {
            Response response = new Response(false);
            response.getHeader().setResultMessage("密码不正确");
            return response;
        } catch (Exception e) {
            Response response = new Response(false);
            response.getHeader().setResultMessage("稍后重试");
            return response;
        }

        return new Response(true);
    }

    @RequestMapping("/register")
    public
    @ResponseBody
    Response register(@RequestBody MovieUser user) throws Exception {
        try {
            String password = RC2Utils.encrypt(user.getPassword());
            user.setPassword(password);
        } catch (Exception e) {
            throw new Exception("加密出错");
        }
        user.setEnabled(true);
        userMapper.addUser(user);
        userMapper.grantUser(user.getUsername(), "ROLE_USER");
        return new Response(true);
    }

    @RequestMapping("/logout")
    public Response logout(HttpServletRequest request, HttpServletResponse response) {

        /**
         * 1 将 HTTP Session 作废，解绑其绑定的所有对象。
         * 2 从SecurityContext移除Authentication 防止并发请求的问题。
         * 3 显式地清楚当前线程的上下文里的值。
         */
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        /**
         * 上下代码等价
         */
        /*HttpSession session = request.getSession();
        session.setAttribute("SPRING_SECURITY_CONTEXT", null);*/
        return new Response(true);
    }
}
